﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace CompileApp.Models;

public class Dfa
{
    // 将DFA的标签映射到以该标签为起点的边上
    public Dictionary<string, List<Edge>> Edges = new();

    // 将NFA的状态集映射到DFA的标签
    private Dictionary<HashSet<string>, string> _labels = new(HashSet<string>.CreateSetComparer());

    // 将DFA的标签映射到NFA的状态集
    private Dictionary<string, HashSet<string>> _significations = new();

    // 将起点标签和路径的元组映射到终点标签
    public Dictionary<Tuple<string, string>, string> Rules = new();


    public HashSet<string>? StartNode = null;
    public HashSet<string> EndNode = new();

    // DFA状态数
    public int StateNum = 0;

    // 展示文本
    private string _resultText = "";

    public HashSet<string> EmptySet = new();

    public Dfa(Nfa nfa)
    {
        // 得到初态的I-closure闭包
        StartNode = _closure(new HashSet<string>() { nfa.StartNode }, nfa);

        List<HashSet<string>> list = new List<HashSet<string>>() { StartNode };
        _labels.Add(StartNode, Convert.ToString(StateNum));
        _significations.Add(Convert.ToString(StateNum), StartNode);
        StateNum++;


        // 进行所有终结符的move运算
        while (list.Count != 0)
        {
            var item = list[0];
            foreach (var terminator in nfa.Terminators)
            {
                if (terminator.Equals("$"))
                {
                    continue;
                }

                var result = _closure(_move(item, nfa, terminator), nfa);

                // 若计算出的状态集未出现过，则将其加入到数组中
                if (!_labels.ContainsKey(result))
                {
                    _labels.Add(result, Convert.ToString(StateNum));
                    _significations.Add(Convert.ToString(StateNum), result);
                    StateNum++;
                    list.Add(result);
                }

                string id = _labels[item];
                string targetId = _labels[result];
                if (result.Contains(nfa.EndNode))
                {
                    EndNode.Add(targetId);
                }

                // || (item.Count == 1 && item.Contains(nfa.EndNode))
                if (item.Count == 0)
                {
                    EmptySet.Add(id);
                }

                string moveStr = terminator;
                switch (terminator)
                {
                    case "Return":
                        moveStr = "\n";
                        break;
                    case "Space":
                        moveStr = " ";
                        break;
                    case "Tab":
                        moveStr = "\t";
                        break;
                    case "左方括号":
                        moveStr = "[";
                        break;
                    case "右方括号":
                        moveStr = "]";
                        break;
                    default:
                        moveStr = terminator;
                        break;
                }

                var tuple = new Tuple<string, string>(id, moveStr);
                Rules.Add(tuple, targetId);
                if (!Edges.ContainsKey(id))
                {
                    Edges.Add(id, new List<Edge>());
                }

                Edges[id].Add(new Edge(id, targetId, moveStr));
            }

            list.Remove(item);
        }
    }

    // move运算
    private HashSet<string> _move(HashSet<string> set, Nfa nfa, string moveStr)
    {
        HashSet<string> result = new();

        foreach (var item in set)
        {
            var tuple = new Tuple<string, string>(item, moveStr);
            if (!nfa.EdgeTable.ContainsKey(tuple))
            {
                continue;
            }

            var nodes = nfa.EdgeTable[tuple];
            foreach (var node in nodes)
            {
                result.Add(node);
            }
        }

        return result;
    }

    // 计算I-closure闭包
    private HashSet<string> _closure(HashSet<string> set, Nfa nfa)
    {
        var toSet = new HashSet<string>(set);
        Dictionary<string, bool> status = new Dictionary<string, bool>();

        var list = set.ToList();

        while (list.Count != 0)
        {
            var item = list[0];
            status[item] = true;
            // var edges = nfa.Edges[item];
            var tuple = new Tuple<string, string>(item, "$");
            if (nfa.EdgeTable.ContainsKey(tuple))
            {
                foreach (var s in nfa.EdgeTable[tuple])
                {
                    toSet.Add(s);
                    if (!status.ContainsKey(s))
                    {
                        list.Add(s);
                    }
                }
            }

            list.Remove(item);
        }

        return toSet;
    }
    

    // 得到展示的字符串
    public string GetDfaText()
    {
        if (_resultText.Equals(""))
        {
            foreach (var (_, edges) in Edges)
            {
                foreach (var edge in edges)
                {
                    _resultText = $"{_resultText}{edge.StartNode}\t{edge.EndNode}\t{edge.TranStr}\n";
                }
            }

            for (int i = 0; i < StateNum; i++)
            {
                _resultText = $"{_resultText}\n状态{i}为:\n";
                HashSet<string> item = _significations[Convert.ToString(i)];
                foreach (var str in item)
                {
                    _resultText = $"{_resultText}{str}\t";
                }

                if (item.Count == 0)
                {
                    _resultText += "空集";
                }

                _resultText += "\n";
            }
        }

        return _resultText;
    }
}